import IUser from "./IUser";



//返回传递给他的任意对象的类
export const isClass: (o: unknown) => string = (o) => {
  if (o === null) return "Null";
  if (o === undefined) return "Undefined";
  // slice(start, end) 方法可提取字符串的某个部分，并以新的字符串返回被提取的部分。
  // 使用 start（包含） 和 end（不包含） 参数来指定字符串提取的部分。
  // start 参数字符串中第一个字符位置为 0, 第二个字符位置为 1, 以此类推，如果是负数表示从尾部截取多少个字符串，slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素（包含最后一个元素）。
  // end 参数如果为负数，-1 指字符串的最后一个字符的位置，-2 指倒数第二个字符，以此类推。
  // console.log(Object.prototype.toString.call(o).slice(8, -1));
  return Object.prototype.toString.call(o).slice(8, -1);
};

// export const isNullOrUndefined: (value: unknown) => boolean = (value) => {
//   let result = false;
//   if (value === null || value == undefined) {
//     result = true;
//   }
//   return result;
// };
export const isNullOrUndefined = (
  value: unknown
): value is null | undefined => {
  let result = false;
  if (value === null || value === undefined) {
    result = true;
  }
  return result;
};

// export const isString: (value: unknown) => boolean = (value) => {
//   let result = true;
//   if (isNullOrUndefined(value) == false && isClass(value) != "String") {
//     result = false;
//   }
//   return result;
// };
// typeof 只能检查基本数据类型（不能检查复杂数据类型），比如下面这些：
// string | number | bigint | boolean | symbol | undefined | object | function
export const isString = (value: unknown): value is string => {
  return typeof value === "string";
};

// export const isObject: (value: unknown) => boolean = function (value) {
//   let result = true;
//   if (isNullOrUndefined(value) == false && isClass(value) != "Object") {
//     result = false;
//   }
//   return result;
// };
// typeof 只能检查基本数据类型（不能检查复杂数据类型），比如下面这些：
// string | number | bigint | boolean | symbol | undefined | object | function
export const isObject = function (value: unknown): value is object {
  return typeof value === "object";
};

export const isArray: (value: unknown) => boolean = (value) => {
  let result = true;
  if (isNullOrUndefined(value) == false && isClass(value) != "Array") {
    result = false;
  }
  return result;
};
// export const isNumber: (value: unknown) => boolean = (value) => {
//   let result = true;
//   if (isNullOrUndefined(value) == false && isClass(value) != "Number") {
//     result = false;
//   }
//   return result;
// };
// typeof 只能检查基本数据类型（不能检查复杂数据类型），比如下面这些：
// string | number | bigint | boolean | symbol | undefined | object | function
export const isNumber = function (value: unknown): value is number {
  return typeof value === "number";
};

// export const isBoolean: (value: unknown) => boolean = (value) => {
//   let result = true;
//   if (isNullOrUndefined(value) == false && isClass(value) != "Boolean") {
//     result = false;
//   }
//   return result;
// };
// typeof 只能检查基本数据类型（不能检查复杂数据类型），比如下面这些：
// string | number | bigint | boolean | symbol | undefined | object | function
export const isBoolean = function (value: unknown): value is boolean {
  return typeof value === "boolean";
};

export const isRegExp: (value: unknown) => boolean = (value) => {
  let result = true;
  if (isNullOrUndefined(value) == false && isClass(value) != "RegExp") {
    result = false;
  }
  return result;
};
export const isDate: (value: unknown) => boolean = (value) => {
  let result = true;
  if (isNullOrUndefined(value) == false && isClass(value) != "Date") {
    result = false;
  }
  return result;
};

// export const isSymbol: (value: unknown) => boolean = (value) => {
//   let result = true;
//   if (isNullOrUndefined(value) == false && isClass(value) != "Symbol") {
//     result = false;
//   }
//   return result;
// };
// typeof 只能检查基本数据类型（不能检查复杂数据类型），比如下面这些：
// string | number | bigint | boolean | symbol | undefined | object | function
export const isSymbol = function (value: unknown): value is symbol {
  return typeof value === "symbol";
};

export const isFunction: (value: unknown) => boolean = (value) => {
  let result = true;
  if (isNullOrUndefined(value) == false && isClass(value) != "Function") {
    result = false;
  }
  return result;
};
// export const isFunction = function (
//   value: unknown
// ): value is Function {
//   return typeof value === "function";
// };

export function isValidKey(
  key: string | number | symbol,
  tobject: object
): key is keyof typeof tobject {
  // console.log(key in object);
  return key in tobject;
}
// 写一个类型复制的类型工具
// type Copy<T> = {
//   [key in keyof T]: T[key]
// }
// function getObj<T extends object, K extends keyof T>(obj: T, key: K) {
//   return obj[key];
// }
interface resultType {
  // 临时某一行关闭校验
  // eslint-disable-next-line
  [propName: string | symbol]: object;
}
// type Partial<T> = {
//   [P in keyof T]?: T[P];
// };
////////////////////////////////////////////////////////////////////////////////
//  实现对象的深度克隆 start
////////////////////////////////////////////////////////////////////////////////
//深度克隆
export const deepClone: (obj: object) => object = (obj) => {
  let result: resultType | object[];
  const oClass: string = isClass(obj);
  if (obj === undefined || obj === null) {
    return obj;
  }
  // obj 是Object对象
  if (oClass === "Object") {
    result = {};
  } else if (oClass === "Array") {
    // obj 是Array
    result = [];
  } else {
    return obj;
  }
  ////////////////////////////////////////
  // 拷贝自身
  // Reflect.ownKeys返回一个数组，包含对象自身的（不含继承的）所有键名，不管键名是 Symbol 或字符串，也不管是否可枚举。
  for (const key of Reflect.ownKeys(obj)) {
    if (isSymbol(key)) {
      if (
        key.toString() == "Symbol(Symbol.iterator)" ||
        key.toString() == "Symbol(Symbol.unscopables)"
      )
        continue;
    }
    let copy: object = {};
    if (isValidKey(key, obj)) {
      copy = obj[key];
    }
    // const copy: any = obj[key];
    if (isClass(copy) == "Object") {
      if (Array.isArray(result)) {
        result.push(deepClone(copy));
      } //递归调用
      else {
        result[key] = deepClone(copy);
      }
    } else if (isClass(copy) == "Array") {
      if (Array.isArray(result)) {
        result.push(deepClone(copy));
      } //递归调用
      else {
        result[key] = deepClone(copy);
      }
    } else {
      if (isNullOrUndefined(copy)) {
        Reflect.defineProperty(result, key, {
          value: copy,
          writable: true,
          enumerable: true,
          configurable: true,
        });
      } else {
        const objopd = Reflect.getOwnPropertyDescriptor(obj, key);
        if (objopd != undefined) {
          Reflect.defineProperty(result, key, objopd);
        }
      }
    }
  }
  ////////////////////////////////////////////////////////////////////////
  //   //拷贝原型的属性和方法-》 Object.keys返回一个数组，包括对象自身的（不含继承的）所有可枚举属性（不含 Symbol 属性）的键名。
  //   const protoObj: any = Reflect.getPrototypeOf(obj);
  const tPrototype: object | null = Reflect.getPrototypeOf(obj);
  if (tPrototype === null || tPrototype === undefined) {
    Reflect.setPrototypeOf(result, null);
  } else {
    const protoObj: object = tPrototype;
    if (protoObj == Array.prototype) {
      // 防止出现类数组对象
      Reflect.setPrototypeOf(result, Array.prototype);
    } else {
      Reflect.setPrototypeOf(result, {});
    }
    const resultProtoObj: resultType | object[] | object | null =
      Reflect.getPrototypeOf(result);
    if (resultProtoObj != null) {
      //拷贝原型-》属性和方法
      if (protoObj != null && protoObj != undefined) {
        for (const key of Reflect.ownKeys(protoObj)) {
          // const copy = protoObj[key];
          if (isSymbol(key)) {
            // console.log(key.toString());
            if (
              key.toString() == "Symbol(Symbol.iterator)" ||
              key.toString() == "Symbol(Symbol.unscopables)"
            )
              continue;
          }
          // const copy = protoObj[key] || obj[key]; // 防止class中的getter setter 原型无法读取值，所以要从实例属性上取下值
          let copy: object = {};
          if (isValidKey(key, protoObj)) {
            copy = protoObj[key];
            if (!copy) {
              if (isValidKey(key, obj)) {
                copy = obj[key];
              }
            }
          }
          if (isClass(copy) == "Object") {
            // resultProtoObj[key] = arguments.callee(copy); //递归调用
            if (Array.isArray(resultProtoObj)) {
              resultProtoObj.push(deepClone(copy));
            } //递归调用
            else {
              (<resultType>resultProtoObj)[key] = deepClone(copy); //递归调用
            }
          } else if (isClass(copy) == "Array") {
            // resultProtoObj[key] = arguments.callee(copy);
            if (Array.isArray(resultProtoObj)) {
              resultProtoObj.push(deepClone(copy));
            } //递归调用
            else {
              (<resultType>resultProtoObj)[key] = deepClone(copy); //递归调用
            }
          } else {
            // resultProtoObj[key] = copy;
            // console.log("bbbb__" + isClass(copy));
            // console.log(key);
            if (isNullOrUndefined(copy)) {
              Reflect.defineProperty(resultProtoObj, key, {
                value: copy,
                writable: true,
                enumerable: true,
                configurable: true,
              });
            } else {
              const protoObjopd = Reflect.getOwnPropertyDescriptor(
                protoObj,
                key
              );
              if (protoObjopd != undefined) {
                Reflect.defineProperty(resultProtoObj, key, protoObjopd);
              }
            }
          }
        }
      }
    }
  }
  ////////////////////////////////////////////////////////////////////////
  return result;
};
///////////////////////////////////////////////////////
// //  实现对象的深度克隆 start
// ////////////////////////////////////////////////////////////////////////////////
// //深度克隆
// export const deepClone = function (obj: any) {
//   let result: any;
//   const oClass: string = isClass(obj);
//   //确定result的类型
//   // if (
//   //   isClass(obj) == "Object" ||
//   //   isClass(obj) == "Foundation" ||
//   //   isClass(obj) == "FoundationDetail" ||
//   //   isClass(obj) == "FoundationPaiHang" ||
//   //   isClass(obj) == "FoundationTongJi" ||
//   //   isClass(obj) == "User"
//   // ) {
//   if (obj === undefined || obj === null) {
//     return obj;
//   }
//   if (oClass === "Object") {
//     result = {};
//   } else if (oClass === "Array") {
//     result = [];
//   } else {
//     // console.log(typeof obj);
//     return obj;
//   }
//   ////////////////////////////////////////
//   // 拷贝自身
//   ////////////////////////////////////////
//   // for...in循环遍历对象自身的和继承的可枚举属性（不含 Symbol 属性）。
//   // for (key in obj) {
//   // 拷贝自身属性和方法-》 Object.keys返回一个数组，包括对象自身的（不含继承的）所有可枚举属性（不含 Symbol 属性）的键名。
//   // for (key of Object.keys(obj)) {

//   // Reflect.ownKeys返回一个数组，包含对象自身的（不含继承的）所有键名，不管键名是 Symbol 或字符串，也不管是否可枚举。
//   for (const key of Reflect.ownKeys(obj)) {
//     if (key === undefined || key === null) {
//       continue;
//     }
//     if (isSymbol(key)) {
//       // console.log(key.toString());
//       if (
//         key.toString() == "Symbol(Symbol.iterator)" ||
//         key.toString() == "Symbol(Symbol.unscopables)"
//       )
//         continue;
//     }

//     // let copy: unknown;
//     // if (isValidKey(key, obj)) {
//     //   copy = obj[key];
//     // }
//     const copy: any = obj[key];
//     // if (
//     //   isClass(copy) == "Object" ||
//     //   isClass(copy) == "Foundation" ||
//     //   isClass(copy) == "FoundationDetail" ||
//     //   isClass(copy) == "FoundationPaiHang" ||
//     //   isClass(copy) == "FoundationTongJi" ||
//     //   isClass(copy) == "User"
//     // ) {
//     if (isClass(copy) == "Object") {
//       // result[key] = arguments.callee(copy); //递归调用
//       result[key] = deepClone(copy); //递归调用
//     } else if (isClass(copy) == "Array") {
//       // result[key] = arguments.callee(copy);
//       result[key] = deepClone(copy); //递归调用
//     } else {
//       // result[key] = copy;;
//       // console.log("aaaa__" + isClass(copy));
//       // console.log(key);
//       if (isNullOrUndefined(copy)) {
//         Reflect.defineProperty(result, key, {
//           value: copy,
//           writable: true,
//           enumerable: true,
//           configurable: true,
//         });
//       } else {
//         Reflect.defineProperty(
//           result,
//           key,
//           Reflect.getOwnPropertyDescriptor(
//             obj,
//             key
//           ) as TypedPropertyDescriptor<any>
//         );
//       }
//       // Object.getOwnPropertyDescriptor(obj, key);
//     }
//   }
//   ////////////////////////////////////////
//   //拷贝原型
//   ////////////////////////////////////////
//   //拷贝原型的属性和方法-》 Object.keys返回一个数组，包括对象自身的（不含继承的）所有可枚举属性（不含 Symbol 属性）的键名。
//   const protoObj: any = Reflect.getPrototypeOf(obj);
//   if (protoObj == Array.prototype) {
//     // 防止出现类数组对象
//     Reflect.setPrototypeOf(result, Array.prototype);
//   } else {
//     Reflect.setPrototypeOf(result, {});
//   }
//   const resultProtoObj: any = Reflect.getPrototypeOf(result);
//   //拷贝原型-》属性和方法
//   if (isNullOrUndefined(protoObj) == false) {
//     for (const key of Reflect.ownKeys(protoObj)) {
//       // const copy = protoObj[key];
//       if (isSymbol(key)) {
//         // console.log(key.toString());
//         if (
//           key.toString() == "Symbol(Symbol.iterator)" ||
//           key.toString() == "Symbol(Symbol.unscopables)"
//         )
//           continue;
//       }
//       const copy = protoObj[key] || obj[key]; // 防止class中的getter setter 原型无法读取值，所以要从实例属性上取下值
//       // if (
//       //   isClass(copy) == "Object" ||
//       //   isClass(copy) == "Foundation" ||
//       //   isClass(copy) == "FoundationDetail" ||
//       //   isClass(copy) == "FoundationPaiHang" ||
//       //   isClass(copy) == "FoundationTongJi" ||
//       //   isClass(copy) == "User"
//       // ) {
//       if (isClass(copy) == "Object") {
//         // resultProtoObj[key] = arguments.callee(copy); //递归调用
//         resultProtoObj[key] = deepClone(copy); //递归调用
//       } else if (isClass(copy) == "Array") {
//         // resultProtoObj[key] = arguments.callee(copy);
//         resultProtoObj[key] = deepClone(copy); //递归调用
//       } else {
//         // resultProtoObj[key] = copy;
//         // console.log("bbbb__" + isClass(copy));
//         // console.log(key);
//         if (isNullOrUndefined(copy)) {
//           Reflect.defineProperty(resultProtoObj, key, {
//             value: copy,
//             writable: true,
//             enumerable: true,
//             configurable: true,
//           });
//         } else {
//           Reflect.defineProperty(
//             resultProtoObj,
//             key,
//             Reflect.getOwnPropertyDescriptor(
//               protoObj,
//               key
//             ) as TypedPropertyDescriptor<any>
//           );
//         }
//       }
//     }
//   }
//   return result;
// };
// *
//  * 日期对象转为日期字符串
//  * @param date 需要格式化的日期对象
//  * @param sFormat 输出格式,默认为yyyy-MM-dd                         年：y，月：M，日：d，时：h，分：m，秒：s
//  * @example  dateFormat(new Date())                               "2017-02-28"
//  * @example  dateFormat(new Date(),'yyyy-MM-dd')                  "2017-02-28"
//  * @example  dateFormat(new Date(),'yyyy-MM-dd hh:mm:ss')         "2017-02-28 09:24:00"
//  * @example  dateFormat(new Date(),'hh:mm')                       "09:24"
//  * @example  dateFormat(new Date(),'yyyy-MM-ddThh:mm:ss+08:00')   "2017-02-28T09:24:00+08:00"
//  * @returns {string}
const dateFormat: (value: Date, dateFormat: string) => string = (
  value,
  dateFormat
) => {
  const date = new Date(Number(value));
  // if (date.toString() === "Invalid Date") {
  //   date = new Date(value.replace(/\-/g, "/"));
  // }
  const time = {
    Year: 0,
    TYear: "0",
    Month: 0,
    TMonth: "0",
    Day: 0,
    TDay: "0",
    Hour: 0,
    THour: "0",
    hour: 0,
    Thour: "0",
    Minute: 0,
    TMinute: "0",
    Second: 0,
    TSecond: "0",
    Millisecond: 0,
  };
  time.Year = date.getFullYear();
  time.TYear = String(time.Year).substr(2);
  time.Month = date.getMonth() + 1;
  time.TMonth = time.Month < 10 ? "0" + time.Month : String(time.Month);
  time.Day = date.getDate();
  time.TDay = time.Day < 10 ? "0" + time.Day : String(time.Day);
  time.Hour = date.getHours();
  time.THour = time.Hour < 10 ? "0" + time.Hour : String(time.Hour);
  time.hour = time.Hour < 13 ? time.Hour : time.Hour - 12;
  time.Thour = time.hour < 10 ? "0" + time.hour : String(time.hour);
  time.Minute = date.getMinutes();
  time.TMinute = time.Minute < 10 ? "0" + time.Minute : String(time.Minute);
  time.Second = date.getSeconds();
  time.TSecond = time.Second < 10 ? "0" + time.Second : String(time.Second);
  time.Millisecond = date.getMilliseconds();

  return dateFormat
    .replace(/yyyy/gi, String(time.Year))
    .replace(/yyy/gi, String(time.Year))
    .replace(/yy/gi, time.TYear)
    .replace(/y/gi, time.TYear)
    .replace(/MM/g, time.TMonth)
    .replace(/M/g, String(time.Month))
    .replace(/dd/gi, time.TDay)
    .replace(/d/gi, String(time.Day))
    .replace(/HH/g, time.THour)
    .replace(/H/g, String(time.Hour))
    .replace(/hh/g, time.Thour)
    .replace(/h/g, String(time.hour))
    .replace(/mm/g, time.TMinute)
    .replace(/m/g, String(time.Minute))
    .replace(/ss/gi, time.TSecond)
    .replace(/s/gi, String(time.Second))
    .replace(/fff/gi, String(time.Millisecond));
};

// export const getUrlParameters: (urlString: string) => Record<string, string> = (
//   urlString
// ) => {
//   const url = new URL(urlString); // 创建 URL 对象
//   const params = new URLSearchParams(url.search); // 从 URL 对象中提取查询字符串并转换为 URLSearchParams 对象
//   return Object.fromEntries(params.entries()); // 将 URLSearchParams 对象转换为键值对形式的记录（Record）
// };

export const isIUser = function (obj: IUser): obj is IUser {
  return typeof obj.name === "string";
};

export default {
  isClass,
  isNullOrUndefined,
  isString,
  isObject,
  isArray,
  isNumber,
  isBoolean,
  isRegExp,
  isDate,
  isSymbol,
  isFunction,
  deepClone,
  dateFormat,
  // getUrlParameters,
  isIUser,
};
